/*
 * This file is part of the K-net login application.
 *
 * K-net login application is free software: you can redistribute it
 * and/or modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation, either version 3 of 
 * the License, or (at your option) any later version.
 *
 * K-net login is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License 
 * along with the K-net login application.
 * If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * Copyright (C) 2011 Ulrik Andersen.
 * Copyright (C) 2011 Kasper Sjørslev.
 */

package dk.knet.login;

import android.util.Log;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelShell;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;

public class FirewallConnection extends Thread implements Runnable {
	
	private static final String TAG = "FirewallConnection";
	
	private boolean isMoribund = false;
	private String host, user, pass;	
	private Ping pinger;
	private JSch jsch;	
	private Session session;
	private Channel channel;
	private PipedInputStream in;
	private PipedOutputStream out;
	
	public FirewallConnection(String h,String u,String p) {		
		host = h;
		user = u;
		pass = p;
		
		JSch.setLogger(new MyLogger());
		jsch = new JSch();
		pinger = new Ping();
	}
	
	private volatile Thread runner;

	public synchronized void startThread(){
		if(runner == null){
			runner = new Thread(this);
			runner.start();
		}
	}

	public synchronized void stopThread(){
		if(runner != null){
			Thread moribund = runner;
			runner = null;
			moribund.interrupt();
		}
	}
	
	public void run() {
		while(true && Thread.currentThread() == runner) {
			if(session!=null) {
				if(!session.isConnected()) {
					setStatus(MainService.TRYING);
				}
			}
			if(channel!=null) {
				if(!channel.isConnected()) {
					setStatus(MainService.TRYING);
				}
			}
			
			if(getStatus() != MainService.CONN) 
				if(MainService.LOG) Log.i(TAG, "Not connected...");
				setStatus(MainService.TRYING);
				connect();			// autoconnect
			
				if(MainService.LOG) Log.i(TAG, "Sleeping...");
			try {
				Thread.currentThread();
				Thread.sleep(20000);
			} 
			catch (InterruptedException e) {
			}
			if(MainService.LOG) Log.i(TAG, "Wake up...");
		}
		if(MainService.LOG) Log.i(TAG, "Firewall thread interrupted.");
//		setStatus(MainService.NO_CONN);
	}	
	
	public void disconnect() {
		if(MainService.LOG) Log.i(TAG, "Disconnecting...");
		isMoribund = true;
		if(getStatus() == MainService.CONN) {
			channel.disconnect();
			session.disconnect();
		}
		if(MainService.LOG) Log.i(TAG, "Disconnected!");
	}
	
	public void connect() {
	
		if(getStatus() == MainService.CONN) {
			if(MainService.LOG) Log.i(TAG, "Already connected...");
			return;
		}
		
		if(!pinger.ping(host)) {
			if(MainService.LOG) Log.e(TAG, "No ping response...");
			setStatus(MainService.HOST_ERROR);
			return;
		}
		
       try{
            session = jsch.getSession(user, host, 22);
            
            session.setPassword(pass);
            
            session.setConfig("StrictHostKeyChecking", "no");
            
            session.setServerAliveInterval(30000);

            session.connect(10000);
            
        	channel = session.openChannel("shell");

            ((ChannelShell) channel).setPty(false);
            
            in = new PipedInputStream();
            out = new PipedOutputStream(in);
            
            channel.setOutputStream(out);
            
            channel.connect();            
        }
        catch (Exception e) {       	
        	setStatus(MainService.CONN_ERROR);
        	if(MainService.LOG) Log.i(TAG, "Msg: " + e.getMessage());
        	return;
	    }
        try {
	       	BufferedReader br = new BufferedReader(new InputStreamReader(this.in));
			String s = "";

			if(MainService.LOG) Log.i(TAG,"Prepare for read...");
	           	
	        while ((s = br.readLine()) != null) {
	          	if(MainService.LOG) Log.i(TAG,"Read: " + s);
	           		
	           	int index = s.indexOf("Du er nu logget ind!");
	           	if(index > -1) {
	           		setStatus(MainService.CONN);
	          	}	
			}	
		}
        catch (Exception e) {
        	setStatus(MainService.CONN_ERROR);
        	if(MainService.LOG) Log.i(TAG, "Msg: " + e.getMessage());
        }
	}
	
	private void setStatus(int s) {
		if(!isMoribund) {
			MainService.setStatus(s);
		}
		if(MainService.LOG) Log.i(TAG, "Set status: " + s);
	}
	
	private int getStatus() {
		return MainService.getStatus();
	}
	
	public static class MyLogger implements com.jcraft.jsch.Logger {
		static java.util.Hashtable<Integer, String> name = new java.util.Hashtable<Integer, String>();
		static {
			name.put(new Integer(DEBUG), "DEBUG: ");
			name.put(new Integer(INFO), "INFO: ");
			name.put(new Integer(WARN), "WARN: ");
			name.put(new Integer(ERROR), "ERROR: ");
			name.put(new Integer(FATAL), "FATAL: ");
	    }
	    public boolean isEnabled(int level) {
	    	return true;
	    }
	    public void log(int level, String message) {
	    	if(MainService.LOG) Log.i(TAG,name.get(new Integer(level))  + message);
	    }
	}	
}
